#!/usr/bin/env python3
"""
🤖 AI 客户端封装
支持 OpenAI、Claude 等多种 AI 模型
"""
import json
import os
from abc import ABC, abstractmethod
from enum import Enum
from pathlib import Path
from typing import Any

from dotenv import load_dotenv

# 加载环境变量
load_dotenv()


class AIProvider(Enum):
    """AI 提供商枚举"""

    OPENAI = "openai"
    ANTHROPIC = "anthropic"
    QWEN = "qwen"  # 阿里云通义千问
    MOCK = "mock"  # 用于测试


class AIClient(ABC):
    """AI 客户端抽象基类"""

    @abstractmethod
    def chat(self, messages: list[dict[str, str]], **kwargs: Any) -> str:
        """发送聊天请求"""
        pass

    @abstractmethod
    def analyze_code(self, code: str, prompt: str) -> dict[str, Any]:
        """分析代码"""
        pass


class OpenAIClient(AIClient):
    """OpenAI 客户端"""

    def __init__(self, api_key: str | None = None, model: str = "gpt-4"):
        self.api_key = api_key or os.getenv("OPENAI_API_KEY")
        self.model = model

        if not self.api_key:
            raise ValueError("OPENAI_API_KEY not found in environment variables")

        try:
            import openai

            self.client = openai.OpenAI(api_key=self.api_key)
        except ImportError:
            raise ImportError("Please install openai: pip install openai")

    def chat(self, messages: list[dict[str, str]], **kwargs: Any) -> str:
        """发送聊天请求"""
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            **kwargs,
        )
        return response.choices[0].message.content or ""

    def analyze_code(self, code: str, prompt: str) -> dict[str, Any]:
        """分析代码"""
        messages = [
            {"role": "system", "content": prompt},
            {"role": "user", "content": f"请分析以下代码:\n\n```python\n{code}\n```"},
        ]

        response_text = self.chat(messages, temperature=0.3)

        try:
            return json.loads(response_text)
        except json.JSONDecodeError:
            return {"raw_response": response_text, "parsed": False}


class AnthropicClient(AIClient):
    """Anthropic Claude 客户端"""

    def __init__(self, api_key: str | None = None, model: str = "claude-3.5-sonnet"):
        self.api_key = api_key or os.getenv("ANTHROPIC_API_KEY")
        self.model = model

        if not self.api_key:
            raise ValueError("ANTHROPIC_API_KEY not found in environment variables")

        try:
            import anthropic

            self.client = anthropic.Anthropic(api_key=self.api_key)
        except ImportError:
            raise ImportError("Please install anthropic: pip install anthropic")

    def chat(self, messages: list[dict[str, str]], **kwargs: Any) -> str:
        """发送聊天请求"""
        # Claude 需要分离 system 消息
        system_message = ""
        user_messages = []

        for msg in messages:
            if msg["role"] == "system":
                system_message = msg["content"]
            else:
                user_messages.append(msg)

        response = self.client.messages.create(
            model=self.model,
            system=system_message,
            messages=user_messages,
            max_tokens=4096,
            **kwargs,
        )

        return response.content[0].text

    def analyze_code(self, code: str, prompt: str) -> dict[str, Any]:
        """分析代码"""
        messages = [
            {"role": "system", "content": prompt},
            {"role": "user", "content": f"请分析以下代码:\n\n```python\n{code}\n```"},
        ]

        response_text = self.chat(messages, temperature=0.3)

        try:
            return json.loads(response_text)
        except json.JSONDecodeError:
            return {"raw_response": response_text, "parsed": False}


class QwenClient(AIClient):
    """阿里云通义千问客户端"""

    def __init__(self, api_key: str | None = None, model: str = "qwen-plus"):
        self.api_key = api_key or os.getenv("QWEN_API_KEY")
        self.model = model
        self.base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"

        if not self.api_key:
            raise ValueError("QWEN_API_KEY not found in environment variables")

        try:
            import openai

            # 阿里云 Qwen 使用 OpenAI 兼容接口
            self.client = openai.OpenAI(
                api_key=self.api_key,
                base_url=self.base_url,
            )
        except ImportError:
            raise ImportError("Please install openai: pip install openai")

    def chat(self, messages: list[dict[str, str]], **kwargs: Any) -> str:
        """发送聊天请求"""
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            **kwargs,
        )
        return response.choices[0].message.content or ""

    def analyze_code(self, code: str, prompt: str) -> dict[str, Any]:
        """分析代码"""
        messages = [
            {"role": "system", "content": prompt},
            {"role": "user", "content": f"请分析以下代码:\n\n```python\n{code}\n```"},
        ]

        response_text = self.chat(messages, temperature=0.3)

        try:
            return json.loads(response_text)
        except json.JSONDecodeError:
            return {"raw_response": response_text, "parsed": False}


class MockAIClient(AIClient):
    """模拟 AI 客户端（用于测试）"""

    def chat(self, messages: list[dict[str, str]], **kwargs: Any) -> str:
        """返回模拟响应"""
        return json.dumps(
            {
                "summary": "模拟响应：代码检查通过",
                "issues": [],
                "confidence": 0.95,
                "mock": True,
            }
        )

    def analyze_code(self, code: str, prompt: str) -> dict[str, Any]:
        """返回模拟分析结果"""
        return {
            "summary": "模拟分析：未发现问题",
            "issues": [],
            "confidence": 0.95,
            "mock": True,
        }


class AIClientFactory:
    """AI 客户端工厂"""

    @staticmethod
    def create(provider: AIProvider = AIProvider.OPENAI, **kwargs: Any) -> AIClient:
        """创建 AI 客户端实例"""
        if provider == AIProvider.OPENAI:
            return OpenAIClient(**kwargs)
        elif provider == AIProvider.ANTHROPIC:
            return AnthropicClient(**kwargs)
        elif provider == AIProvider.QWEN:
            return QwenClient(**kwargs)
        elif provider == AIProvider.MOCK:
            return MockAIClient()
        else:
            raise ValueError(f"Unsupported AI provider: {provider}")


def load_prompt(prompt_name: str) -> str:
    """
    加载 prompt 模板

    Args:
        prompt_name: prompt 文件名（不含 .txt 扩展名）

    Returns:
        prompt 内容
    """
    prompt_file = Path("prompts") / f"{prompt_name}.txt"

    if not prompt_file.exists():
        raise FileNotFoundError(f"Prompt file not found: {prompt_file}")

    with open(prompt_file, "r", encoding="utf-8") as f:
        return f.read()


def render_prompt(template: str, **variables: Any) -> str:
    """
    渲染 prompt 模板（支持简单的变量替换）

    Args:
        template: prompt 模板内容
        **variables: 要替换的变量

    Returns:
        渲染后的 prompt
    """
    result = template
    for key, value in variables.items():
        placeholder = f"{{{key}}}"
        result = result.replace(placeholder, str(value))
    return result


# 示例使用
if __name__ == "__main__":
    # 使用模拟客户端进行测试
    print("🧪 测试 AI 客户端...")

    client = AIClientFactory.create(AIProvider.MOCK)

    # 加载 prompt
    try:
        prompt = load_prompt("ai_quality_guard")
        print(f"✅ 成功加载 prompt: ai_quality_guard")
    except FileNotFoundError as e:
        print(f"❌ {e}")
        prompt = "你是代码质量检查助手"

    # 分析代码
    sample_code = """
def get_user(user_id):
    return db.query(User).get(user_id)
"""

    result = client.analyze_code(sample_code, prompt)
    print(f"\n📊 分析结果:")
    print(json.dumps(result, indent=2, ensure_ascii=False))
